package priv.lhy.sso.intercept;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import priv.lhy.annotation.Anoymous;
import priv.lhy.constans.WebConstant;
import priv.lhy.constants.ResponseCodeEnum;
import priv.lhy.dto.CheckAuthRequest;
import priv.lhy.dto.CheckAuthResponse;
import priv.lhy.sso.controller.BaseController;
import priv.lhy.user.IUserCoreService;
import priv.lhy.utils.CookieUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.lang.reflect.Method;

/**
 * author : lihy
 * date : 2019/2/12 10:48
 * token验证拦截器
 */
public class TokenInterceptor extends HandlerInterceptorAdapter {

    private static final String ACCESS_TOKEN = "access_token";

    @Autowired
    IUserCoreService userCoreService;

    /***
     * 拦截请求，进行权限验证
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //非spring管理对象不处理
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        //有anoymous注解的对象/方法不处理
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Object bean = handlerMethod.getBean();
        if (isAnoymous(handlerMethod)) {
            return true;
        }

        //未继承BaseController的对象提示错误
        if (!(bean instanceof BaseController)) {
            throw new RuntimeException("must extend BaseController");
        }

        //获取客户端token
        String token = CookieUtils.getCookieValue(request, ACCESS_TOKEN);
        boolean isAjax = CookieUtils.isAjax(request);
        if (StringUtils.isEmpty(token)) {   //token为空
            if (isAjax) {   //如果是ajax请求则返回错误json信息
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().write("{\"code\":\"-1\", \"msg\":\"error\"}");
                return false;
            }
            //非ajax请求则跳转到登录页
            response.sendRedirect(WebConstant.SSO_ACCESS_URL);
            return false;
        }

        //token不为空则验证token
        CheckAuthRequest checkAuthRequest = new CheckAuthRequest();
        checkAuthRequest.setToken(token);
        CheckAuthResponse checkAuthResponse = userCoreService.validToken(checkAuthRequest);

        //验证通过则将uid写入threadlocal保存
        if (ResponseCodeEnum.SUCCESS.getCode().equals(checkAuthResponse.getCode())) {
            BaseController baseController = (BaseController) bean;
            baseController.setUid(checkAuthResponse.getUid());
            return super.preHandle(request, response, handler);
        }
        //验证失败
        if (isAjax) {   //如果是ajax请求者返回json信息
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write("{\"code\":\"" + checkAuthResponse.getCode() + "\"" + ",\"msg\":\"" + checkAuthResponse.getMsg() + "\"}");
            return false;
        }
        //非ajax请求则跳转到登录页
        response.sendRedirect(WebConstant.SSO_ACCESS_URL);
        return false;
    }

    /***
     * 判断是否有anoymous注解
     * @param handlerMethod
     * @return
     */
    private boolean isAnoymous(HandlerMethod handlerMethod) {
        Object bean = handlerMethod.getBean();
        Class clazz = bean.getClass();
        //类上加注解
        if (clazz.getAnnotation(Anoymous.class) != null) {
            return true;
        }
        //方法上加注解
        Method method = handlerMethod.getMethod();
        return method.getAnnotation(Anoymous.class) != null;
    }
}
